package com.xci.platform.auth.service;

import com.github.pagehelper.Page;
import com.xci.platform.annotation.OperateUser;
import com.xci.platform.annotation.QueryMap;
import com.xci.platform.auth.core.AuthConstant;
import com.xci.platform.auth.core.HistoryModel;
import com.xci.platform.auth.core.HistoryOperateType;
import com.xci.platform.auth.dao.ContentDao;
import com.xci.platform.auth.entity.ContentEntity;
import com.xci.platform.core.BoolMessage;
import com.xci.platform.helper.CoreHelper;
import com.xci.platform.helper.StringHelper;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;

/**
 * 系统内容字典服务
 */
@Service
@CacheConfig(cacheNames = "contentCache")
public class ContentService extends AuthBaseService {

    /**
     * 内容字典数据访问对象
     */
    @Resource
    private ContentDao contentDao;

    /**
     * 缓存对象
     */
    @Resource(name = "contentCache")
    private Cache contentCache;

    /**
     * 保存内容字典
     *
     * @param entity   内容字典对象
     * @param isCreate 是否新建
     */
    @Validated
    @OperateUser
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = "'content:code:'+#entity.code")
    public BoolMessage save(ContentEntity entity, Boolean isCreate) {
        //添加名称简拼
        if (StringHelper.isBlank(entity.getSpell())) {
            entity.setSpell(StringHelper.getSpell(entity.getName()));
        }
        // entity.setContentValue(Util.cleanHtml(entity.getContentValue()));
        //内容字典名称验证
        if (contentDao.existByCode(entity.getCode(), entity.getId())) {
            String msg = StringHelper.format("内容字典编码 {} 已经存在", entity.getName());
            return new BoolMessage(false, msg);
        }

        String msg;
        long startTime = CoreHelper.startWatch();
        if (isCreate) {
            msg = StringHelper.format("新增内容字典 {}({})", entity.getCode(), entity.getName());
            contentDao.insert(entity);
            //region 历史记录
            operateHistory(buildHistory()
                    .operateType(HistoryOperateType.Insert)
                    .keyValue(entity.getId())
                    .message(msg)
                    .after(entity)
            );
            //endregion
        } else {
            msg = StringHelper.format("修改内容字典 {}({})", entity.getCode(), entity.getName());
            ContentEntity oldEntity = queryById(entity.getId());
            contentDao.update(entity);
            //region 历史记录
            operateHistory(buildHistory()
                    .operateType(HistoryOperateType.Update)
                    .keyValue(entity.getId())
                    .message(msg)
                    .before(oldEntity)
                    .after(entity)
            );
            //endregion
        }
        // 操作日志
        operateLog(AuthConstant.SystemModule.Content, msg, CoreHelper.stopWatch(startTime));
        return BoolMessage.True;
    }

    /**
     * 删除内容字典
     *
     * @param id 内容字典主键数组
     */
    @Validated
    @Transactional(rollbackFor = Exception.class)
    public BoolMessage delete(@NotEmpty(message = "请指定删除的内容字典主键") String id) {
        ContentEntity oldEntity = contentDao.queryById(id);
        if (oldEntity == null) return BoolMessage.True;

        long startTime = CoreHelper.startWatch();
        contentDao.delete(id);
        contentCache.evict(StringHelper.format("content:code:{}",oldEntity.getCode()));
        String msg = StringHelper.format("删除内容字典 {}({})", oldEntity.getCode(), oldEntity.getName());
        //region 历史记录
        operateHistory(buildHistory()
                .operateType(HistoryOperateType.Delete)
                .keyValue(id)
                .message(msg)
                .before(oldEntity)
        );
        //endregion
        // 操作日志
        operateLog(AuthConstant.SystemModule.Content, msg, CoreHelper.stopWatch(startTime));
        return BoolMessage.True;
    }

    /**
     * 根据内容字典主键获取内容字典对象
     *
     * @param id 内容字典主键
     * @return 返回指定内容字典主键的内容字典对象
     */
    @Validated
    public ContentEntity queryById(@NotNull(message = "请指定内容字典主键") String id) {
        return contentDao.queryById(id);
    }

    /**
     * 根据内容字典编码获取内容字典值
     *
     * @param code 内容字典编码
     * @return 返回内容字典编码对应的内容字典值
     */
    @Validated
    @Cacheable(key = "'content:code:'+#code")
    public ContentEntity queryByCode(@NotNull(message = "请指定内容字典编码") String code) {
        return contentDao.queryByCode(code);
    }

    /**
     * 根据内容字典编码获取内容字典名称
     * @param code 内容字典编码
     */
    public String queryNameByCode(@NotNull(message = "请指定内容字典编码") String code){
        return contentDao.queryNameByCode(code);
    }

    /**
     * 查询内容字典列表
     *
     * @param params 查询内容字典
     * @return 返回符合查询条件的内容字典列表
     */
    @QueryMap
    public List<ContentEntity> query(Map params) {
        return contentDao.query(params);
    }

    /**
     * 查询内容字典分页列表
     *
     * @param params 查询内容字典
     * @return 返回符合查询条件的内容字典分页列表
     */
    @QueryMap
    public Page<ContentEntity> queryPage(Map params) {
        return (Page<ContentEntity>) contentDao.query(params);
    }

    /**
     * 生成历史记录对象
     */
    private HistoryModel.HistoryModelBuilder buildHistory() {
        return HistoryModel.builder()
                .tableName("sys_content")
                .tableCaption("系统内容字典")
                .keyName("id");
    }
}
